﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sheeps;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;

namespace SheepWpfInterface
{
    public class PasturePainter
    {
        private List<ObjectShape<ObjectWithPosition>> shapes;

        private GameState State { get; set; }

        private Canvas PaintCanvas { get; set; }

        private Shape pointerShape;

        const double SHEEP_DIAMETER = 10;
        const double SHEEP_RADIUS = SHEEP_DIAMETER / 2;

        const double POINTER_DIAMETER = 15;
        const double POINTER_RADIUS = POINTER_DIAMETER / 2;


        public PasturePainter(GameState gameState, Canvas paintCanvas)
        {
            this.State = gameState;
            this.PaintCanvas = paintCanvas;
            this.shapes = new List<ObjectShape<ObjectWithPosition>>();
        }

        public void InitializeCanvas()
        {

            this.shapes.Clear();
            this.PaintCanvas.Children.Clear();
            Shape shape = null;


            //create pen for sheep
            shape = new Ellipse();
            shape.Width = State.PenSize;
            shape.Height = State.PenSize;
            shape.SetValue(Canvas.LeftProperty, State.PenCenter.X - shape.Width / 2);
            shape.SetValue(Canvas.TopProperty, State.PenCenter.Y - shape.Height / 2);
            shape.Fill = Brushes.Red;
            this.pointerShape = shape;
            PaintCanvas.Children.Add(shape);

            foreach (var sheep in this.State.SheepList)
            {
                shape = new Ellipse();
                shape.Width = SHEEP_DIAMETER;
                shape.Height = SHEEP_DIAMETER/1.2;
                shape.Fill = Brushes.White;
                shape.Stroke = Brushes.Black;
                
                shapes.Add(new ObjectShape<ObjectWithPosition>(sheep, shape));
                PaintCanvas.Children.Add(shape);
            }

            shape = new Ellipse();
            shape.Width = SHEEP_DIAMETER;
            shape.Height = SHEEP_DIAMETER;
            shape.Fill = Brushes.Brown;
            shape.Stroke = Brushes.Yellow;
            shapes.Add(new ObjectShape<ObjectWithPosition>(this.State.Dog, shape));
            PaintCanvas.Children.Add(shape);

            shape = new Ellipse();
            shape.Width = POINTER_DIAMETER;
            shape.Height = POINTER_DIAMETER;
            shape.Stroke = Brushes.BlanchedAlmond;
            shape.StrokeThickness = 2;
            this.pointerShape = shape;
            PaintCanvas.Children.Add(shape);



            this.UpdateCanvas();
        }

        public void UpdateCanvas()
        {
            DoubleAnimation animationX = null;
            DoubleAnimation animationY = null;
            DoubleAnimation animationRot = null;
            TranslateTransform translation = null;
            foreach (var sheepShape in this.shapes)
            {
                animationX = new DoubleAnimation();
                animationY = new DoubleAnimation();
                animationRot = new DoubleAnimation();
                animationX.From = sheepShape.VisualPosition.X;
                animationY.From = sheepShape.VisualPosition.Y;
                animationRot.From = sheepShape.VisualRotation;

                sheepShape.VisualPosition = new Vector3(
                    sheepShape.Object.Position.X - SHEEP_RADIUS,
                    sheepShape.Object.Position.Y - SHEEP_RADIUS,
                    0.0);
                sheepShape.VisualRotation = (180/Math.PI) * sheepShape.Object.NormalizedOrientation.Angle(new Vector3(1, 0, 0));

                animationX.To = sheepShape.VisualPosition.X;
                animationY.To = sheepShape.VisualPosition.Y;
                animationRot.To = sheepShape.VisualRotation;

                animationX.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(0.1));
                animationY.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(0.1));
                animationRot.Duration = new System.Windows.Duration(TimeSpan.FromSeconds(0.1));

                translation = new TranslateTransform();
                RotateTransform rotation = new RotateTransform();
                rotation.CenterX = SHEEP_RADIUS;
                rotation.CenterY = SHEEP_RADIUS;
                TransformGroup transform = new TransformGroup();
                transform.Children.Add(rotation);
                transform.Children.Add(translation);

                sheepShape.ShapeOfObject.RenderTransform = transform;
                translation.BeginAnimation(TranslateTransform.XProperty, animationX);
                translation.BeginAnimation(TranslateTransform.YProperty, animationY);
                rotation.BeginAnimation(RotateTransform.AngleProperty, animationRot);
            }
            
        }

        public void UpdateCursor(double x, double y)
        {
            Vector3 offset = new Vector3(x, y, 0) - State.Dog.Position;
            if (offset.Magnitude > State.Dog.MaxMoveLength)
            {
                offset.Normalize();
                offset *= State.Dog.MaxMoveLength;
            }
            Vector3 nPos = State.Dog.Position + offset;
            TranslateTransform translation = new TranslateTransform();
            translation.X = nPos.X - POINTER_RADIUS;
            translation.Y = nPos.Y - POINTER_RADIUS;
            this.pointerShape.RenderTransform = translation;
        }

        public class ObjectShape<T>
            where T:IWithPosition
        {
            public T Object { get; set; }

            public Shape ShapeOfObject { get; set; }

            public Vector3 VisualPosition { get; set; }

            public double VisualRotation { get; set; }

            public ObjectShape(T objectToBePainted, Shape shapeOfObject)
            {
                this.ShapeOfObject = shapeOfObject;
                this.Object = objectToBePainted;
            }
        }
    }
}
